import json
from gc import enable

from django.shortcuts import render
from django_celery_beat.models import CrontabSchedule, PeriodicTask
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from Cronjob.models import CronJob
from Cronjob.serializers import CronJobSerializer
from rest_framework import permissions
from django.db import transaction


class CronJobView(ModelViewSet):
    queryset = CronJob.objects.all()
    serializer_class = CronJobSerializer
    permission_classes = [permissions.IsAuthenticated]
    filterset_fields = ['project', 'task']

    def create(self, request, *args, **kwargs):
        with transaction.atomic():
            point = transaction.savepoint()
            try:
                # 1、获取前端的请求数据，创建一条定时任务（在CronJob表中添加一条数据）
                result = super().create(request, *args, **kwargs)
                rule = result.data.get("rule").strip().split(" ")
                # 2、在django-celery-beat这个应用的周期任务表中添加一条定时任务
                # 2、获取定期执行的周期规则，创建一条周期规则数据
                cron_dict = dict(zip(["minute", "hour", "day_of_week", "day_of_month", "month_of_year"], rule))

                try:
                    cron = CrontabSchedule.objects.get(**cron_dict)
                except Exception as e:
                    cron = CrontabSchedule.objects.create(**cron_dict)
                PeriodicTask.objects.create(
                    name=result.data.get("name"),
                    task="TestTask.tasks.run_test_task",
                    crontab=cron,
                    kwargs=json.dumps(
                        {
                            "env_id": result.data.get("env"),
                            "task_id": result.data.get("task"),
                            "tester": request.user.username
                        },
                        enabled=request.data.get("status")
                    ))
            except:
                transaction.savepoint_rollback(point)
                return Response({"error": "定时任务创建失败"}, status=500)
            else:
                transaction.savepoint_commit(point)
                return Response(result)
